package network.impl;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.util.LinkedList;
import java.util.List;


import network.NetworkID;
import network.ServerNetworkListener;

import sharedNetwork.NetworkFlags;

class ServerInputThread extends Thread {
	
	private ObjectInputStream reader;
	private NetworkID id;
	private List<ServerNetworkListener> networkListeners;
	private List<ServerInputThreadListener> inputThreadListeners;
	
	private enum Message {
		CLIENT_DISCONNECTED, DISCONNECT, DISCONNECTION_ACCEPTED
	}

	public ServerInputThread(ObjectInputStream inputReader, NetworkID id) {
		reader = inputReader;
		this.id = id;
		networkListeners = new LinkedList<ServerNetworkListener>();
		inputThreadListeners = new LinkedList<ServerInputThreadListener>();
	}
	
	public void addNetworkListener(ServerNetworkListener listener) {
		networkListeners.add(listener);
	}
	
	public void addInputThreadListener(ServerInputThreadListener listener) {
		inputThreadListeners.add(listener);
	}
	
	@Override
	public void run() {
		Object inputObject = null;
		boolean running = true;
		try {
			while (running && (inputObject = reader.readObject()) != null) {
				if (inputObject.equals(NetworkFlags.DISCONNECT)) {
					notifyInputThreadListeners(Message.DISCONNECT);
					notifyNetworkListeners(Message.DISCONNECT);
				} else if (inputObject.equals(NetworkFlags.DISCONNECTION_ACCEPTED)) {
					notifyInputThreadListeners(Message.DISCONNECTION_ACCEPTED);
					notifyNetworkListeners(Message.DISCONNECTION_ACCEPTED);
					running = false;
				} else {
					sendToNetworkListeners(inputObject);
				}
			}
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			System.out.println("Preventing the server from crashing");
			notifyInputThreadListeners(Message.CLIENT_DISCONNECTED);
			notifyNetworkListeners(Message.CLIENT_DISCONNECTED);
		}
	}
	
	private void sendToNetworkListeners(Object obj) {
		for (ServerNetworkListener listener : networkListeners) {
			listener.networkMessageRecieved(obj, id);
		}
	}
	
	private void notifyNetworkListeners(Message message) {
		if (message.equals(Message.CLIENT_DISCONNECTED)) {
			for (ServerNetworkListener listener : networkListeners) {
				listener.clientDisconnected(id);
			}
		} else if (message.equals(Message.DISCONNECT)) {
			for (ServerNetworkListener listener : networkListeners) {
				listener.clientRequestedDisconnection(id);
			}
		} else if (message.equals(Message.DISCONNECTION_ACCEPTED)) {
			for (ServerNetworkListener listener : networkListeners) {
				listener.clientAcceptedDisconnection(id);
			}
		}
	}
	
	private void notifyInputThreadListeners(Message message) {
		if (message.equals(Message.CLIENT_DISCONNECTED)) {
			for (ServerInputThreadListener listener : inputThreadListeners) {
				listener.connectionLost(id);
			}
		} else if (message.equals(Message.DISCONNECT)) {
			for (ServerInputThreadListener listener : inputThreadListeners) {
				listener.disconnect(id);
			}
		} else if (message.equals(Message.DISCONNECTION_ACCEPTED)) {
			for (ServerInputThreadListener listener : inputThreadListeners) {
				listener.disconnectionAccepted(id);
			}
		}
	}
}

